﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using smartcrm.Utilities;
using smartcrm.Models;
using System.IO;
using System.Web.Script.Serialization;

namespace smartcrm.Controllers
{
    public class PortalController : BaseController
    {
        public ActionResult Contact()
        {
            return View();
        }    

        [HttpGet]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            PortalUser user = new PortalUser();
            if (Request.Cookies["PortalUserId"] != null)
            {
                user.LoginId = Request.Cookies["PortalUserId"].Value;
            }

            if (IS_DEMO)
            { 
                user.LoginId = "1001023";
            }

            return View(user);
        }

        [HttpPost]
        public JsonResult Login(PortalUser model, string returnUrl)
        {
            JsonResult result = new JsonResult();
            bool loginSuccess = true;
            Customer customer = Context.Customer.FirstOrDefault(m => m.LoginId == model.LoginId && m.CanLogin);
            if (customer == null)
            {
                loginSuccess = false;
            }
            else
            {
                if (MD5Utility.MD5Encrypt(model.Password) != customer.Password)
                {
                    loginSuccess = false;
                }
            }

            if (loginSuccess)
            {
                HttpCookie cookie = new HttpCookie("PortalUserId");
                cookie.Value = model.LoginId;
                cookie.Expires = DateTime.Now.AddDays(30);
                Response.Cookies.Add(cookie);

                model.Password = string.Empty;
                model.LoginName = customer.CustomerShortName;
                model.CompanyNo = customer.CompanyNo;
                model.CustomerNo = customer.CustomerNo;
                model.CustomerShortName = customer.CustomerShortName;

                Session[PORTAL_LOGIN_USER] = model;

                result.Data = new { code = 0 };
            }
            else
            {
                result.Data = new { code = 1 };
            }
            return result;
        }

        public ActionResult LogOut()
        {
            Session[PORTAL_LOGIN_USER] = null;
            return RedirectToAction("Login", "Portal");
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        [PortalAuthorizationAttribute]
        public ActionResult Index()
        {
            PortalOrderList myOrders = new PortalOrderList();
            myOrders.UnApprovedOrders = GetUnapprovedOrderList();
            myOrders.ApprovedOrders = GetApprovedOrderList();
            myOrders.FileSizeLimitation = Math.Round(AttachmentConfigurate.SizeLimitation, 2).ToString() + " MB";

            return View(myOrders);
        }

        [PortalAuthorizationAttribute]
        private List<OrderInfo> GetUnapprovedOrderList()
        {
            List<OrderInfo> result;
            string customerNo = GetPortLoginUser().CustomerNo;
            IQueryable<OrderInfo> query = (from o in Context.Order.Where(m => m.IsActive && m.CompanyNo == CompanyNo && !m.Approved && m.CustomerNo == customerNo)
                                           select new OrderInfo
                                           {
                                               OrderNo = o.OrderNo,
                                               CreatedTime = o.CreatedTime,
                                               CustomerShortName = o.Customer.CustomerShortName,
                                               OrderName = o.OrderName,
                                               Contact = o.Contact,
                                               PaymentStatus = o.PaymentStatus,
                                               TransactionDate = o.TransactionDate,
                                               CustomerNo = o.CustomerNo,
                                               DetailText = o.DetailText,
                                               Category = o.Category,
                                               CategoryName = o.CategoryName,
                                               Number = o.Number,
                                               OrderStatusNo = o.OrderStatusNo,
                                               StatusDescription = o.OrderStatus.StatusName
                                           });


            result = query.ToList();
            return result;
        }

        [PortalAuthorizationAttribute]
        private List<OrderInfo> GetApprovedOrderList()
        {
            List<OrderInfo> result;
            string customerNo = GetPortLoginUser().CustomerNo;
            IQueryable<OrderInfo> query = (from o in Context.Order.Where(m => m.IsActive && m.Approved && m.CompanyNo == CompanyNo && m.CustomerNo == customerNo)
                                           select new OrderInfo
                                           {
                                               OrderNo = o.OrderNo,
                                               CreatedTime = o.CreatedTime,
                                               CustomerShortName = o.Customer.CustomerShortName,
                                               OrderName = o.OrderName,
                                               Contact = o.Contact,
                                               PaymentStatus = o.PaymentStatus,
                                               TransactionDate = o.TransactionDate,
                                               CustomerNo = o.CustomerNo,
                                               DetailText = o.DetailText,
                                               Category = o.Category,
                                               CategoryName = o.CategoryName,
                                               Number = o.Number,
                                               OrderStatusNo = o.OrderStatusNo,
                                               StatusDescription = o.OrderStatus.StatusName
                                           });


            result = query.ToList();
            foreach (OrderInfo i in result)
            {
                i.PaymentStatusDescription = GetOrderPaymentStatusString(i.PaymentStatus);
            }

            return result;
        }

        [PortalAuthorizationAttribute]
        public JsonResult GetDetail(string OrderNo)
        {
            JsonResult result = new JsonResult();
            string errorMessage = string.Empty;

            OrderInfo detail = new OrderInfo();
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo);
            if (order == null)
            {
                result.Data = new { code = 1, data = MSG_NoEntityFound };
            }
            else
            {
                detail.OrderNo = order.OrderNo;
                detail.OrderName = order.OrderName;
                detail.CustomerShortName = GetPortLoginUser().CustomerShortName;
                detail.Contact = order.Contact;
                detail.Creator = order.Creator;
                detail.Memo = order.Memo;
                detail.TransactionDateString = order.TransactionDate.ToString("yyyy-MM-dd");
                detail.CreatedTimeString = order.CreatedTime.ToString("yyyy-MM-dd HH:mm:ss");
                detail.CategoryName = order.CategoryName;
                detail.DetailText = order.DetailText;
                detail.OrderStatusNo = order.OrderStatusNo;
                detail.PaymentStatus = order.PaymentStatus;
                detail.Number = order.Number;
                detail.ExpectDeliveryDateString = order.ExpectDeliveryDate.HasValue ? order.ExpectDeliveryDate.Value.ToString("yyyy-MM-dd") : "";
                if (order.Approved)
                {
                    detail.StatusDescription = order.OrderStatus.StatusName;
                }
                else
                {
                    detail.StatusDescription = "等待确认";
                }

                detail.PaymentStatusDescription = GetOrderPaymentStatusString(detail.PaymentStatus);
                detail.QueryURL = ORDER_QUERY_URL + order.OrderNo + order.QueryCode;

                if (order.PaymentStatus == ((int)OrderPaymentStatus.Unpaid).ToString() ||
                    order.PaymentStatus == ((int)OrderPaymentStatus.PartPaid).ToString())
                {
                    detail.Css = "OrderStatusUnPaid";
                }
                else
                {
                    detail.Css = "OrderStatusPaid";
                }

                detail.Detail += string.Format("{0}({1})", order.CategoryName, order.DetailText);

                List<OrderLog> logs = order.OrderLog.Where(m => m.IsPublic).ToList();

                detail.steps = new List<JSOrderWorkFlow>();
                List<OrderFlow> orderFlows = Context.OrderFlow.Where(m => m.OrderNo == OrderNo).OrderBy(m => m.OrderFlowNo).ToList();
                foreach (OrderFlow of in orderFlows)
                {
                    JSOrderWorkFlow wf = new JSOrderWorkFlow();
                    wf.StepName = of.WorkFlowStep.WorkFlowStepName;
                    wf.UserName = of.User == null ? "" : of.User.UserName;
                    wf.DateTime = of.EndDate.HasValue ? of.EndDate.Value.ToString("yyyy-MM-dd") : "";
                    wf.IsFinished = of.IsFinished;
                    detail.steps.Add(wf);
                }

                List<OrderAttachment> attachments = Context.OrderAttachment.Where(m => m.OrderNo == OrderNo && m.UploadByCustomer).ToList();
                detail.Attachments = new List<SimpleItemList>();
                foreach (OrderAttachment o in attachments)
                {
                    detail.Attachments.Add(new SimpleItemList() { ItemText = o.FileName, ItemValue = o.AttachmentNo, Addition1 = o.FileTypeImage, Addition2 = string.Format("{0} {1}", o.Creator, o.Createtime.ToString("yyyy-MM-dd")) });
                }

                detail.OrderMemos = new List<SimpleItemList>();
                foreach (OrderMemo o in order.OrderMemo)
                {
                    detail.OrderMemos.Add(new SimpleItemList() { Addition1 = o.Memo, Addition2 = o.Creator, Addition3 = o.Createtime.ToString("yyyy-MM-dd") });
                }

                result.Data = new { code = 0, data = detail };
            }

            return result;
        }

        [PortalAuthorizationAttribute]
        public ActionResult ChangePassword()
        {
            return View();
        }

        [PortalAuthorizationAttribute]
        public JsonResult UpdatePassword(string OldPassword, string newPassword1, string newPassword2)
        {
            JsonResult result = new JsonResult();
            string customerNo = GetPortLoginUser().CustomerNo;
            Customer customer = Context.Customer.FirstOrDefault(m => m.CustomerNo == customerNo);
            
            if (customer == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else if (IS_DEMO)
            {
                result.Data = new { code = 1, message = MSG_IsDemo };
            }
            else if (customer.Password != MD5Utility.MD5Encrypt(OldPassword))
            {
                result.Data = new { code = 1, message = "旧密码不对" };
            }
            else
            {
                customer.Password = MD5Utility.MD5Encrypt(newPassword1);

                Context.SaveChanges();
                result.Data = new { code = 0 };

            }
            return result;
        }

        [PortalAuthorizationAttribute]
        public JsonResult FileUpload(HttpPostedFileBase fileToUpload, string OrderNo)
        {
            JsonResult result = new JsonResult();
            AttachmentConfig config = AttachmentConfigurate;
            string fileRealName = string.Empty;
            string fileExtension = Path.GetExtension(fileToUpload.FileName).Replace(".", "").ToLower();
            if (fileToUpload == null)
            {
                result.Data = new { code = 1, message = "文件不存在" };
            }
            else
            {
                string fileName = Path.Combine(config.RootPath, CompanyNo);
                fileName = Path.Combine(fileName, OrderNo);
                if (!Directory.Exists(fileName))
                {
                    try
                    {
                        Directory.CreateDirectory(fileName);
                    }
                    catch
                    {
                        result.Data = new { code = 1 };
                    }
                }

                fileRealName = Path.GetFileName(fileToUpload.FileName);
                if (fileToUpload.ContentLength > 1024 * 1024 * config.SizeLimitation)
                {
                    result.Data = new { code = 1, message = "文件大小超过限制" };
                }
                else if (fileExtension == ".exe" || fileExtension == ".bat" || fileExtension == ".msi")
                {
                    result.Data = new { code = 1, message = "文件类型不允许" };
                }
                else
                {
                    string fileNo = GetNewIdNumber(IdNumberType.OrderAttachment);
                    fileName = Path.Combine(fileName, fileNo + Path.GetExtension(fileToUpload.FileName));
                    try
                    {
                        fileToUpload.SaveAs(fileName);

                        OrderAttachment attachment = new OrderAttachment();
                        attachment.AttachmentNo = fileNo;
                        attachment.OrderNo = OrderNo;
                        attachment.FileName = fileRealName;
                        attachment.FilePath = fileName;
                        attachment.Createtime = DateTime.Now;
                        attachment.Creator = GetPortLoginUser().LoginName;
                        attachment.UploadByCustomer = true;

                        if (System.IO.File.Exists(Path.Combine(Server.MapPath("/"), @"Images\filetype\" + fileExtension + ".gif")))
                        {
                            attachment.FileTypeImage = "/Images/filetype/" + fileExtension + ".gif";
                        }
                        else
                        {
                            attachment.FileTypeImage = "/Images/filetype/" + "unknown.gif";
                        }

                        Context.OrderAttachment.AddObject(attachment);
                        Context.SaveChanges();

                        result.Data = new { code = 0, fileName = fileRealName, fileNo = fileNo };
                    }
                    catch (Exception ex)
                    {
                        PutbackNo(fileNo, IdNumberType.OrderAttachment);
                        throw ex;
                    }
                }
            }

            return Json(result, "text/plain;charset=UTF-8");
        }

        [PortalAuthorizationAttribute]
        public JsonResult GetOrderAttachments(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            string CustomerNo = GetPortLoginUser().CustomerNo;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CustomerNo == CustomerNo);
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                List<SimpleItemList> attachments = Context.OrderAttachment.Where(m => m.OrderNo == OrderNo && m.UploadByCustomer).Select(m => new SimpleItemList() { ItemText = m.FileName, ItemValue = m.AttachmentNo, Addition1 = m.FileTypeImage, Addition2 = m.Creator }).ToList();
                result.Data = new { code = 0, data = attachments };
            }
            return result;
        }

        [PortalAuthorizationAttribute]
        public ActionResult DownLoadAttachment(string FileNo)
        {
            OrderAttachment attachment = Context.OrderAttachment.FirstOrDefault(m => m.AttachmentNo == FileNo);
            if (attachment == null || attachment.Order.CustomerNo != GetPortLoginUser().CustomerNo)
            {
                throw new NoEntityFound();
            }
            else
            {
                Response.Clear();
                Response.ContentType = "application/octet-stream";// "application/ms-excel/msword";
                Response.AppendHeader("Content-disposition", "attachment; filename=" + attachment.FileName); // open in a new window
                return File(attachment.FilePath, "application / octet - stream");
            }
        }

        /// <summary>
        /// Delete attachment.
        /// The attachment must be uploaded by customer and the order must be unapproved.
        /// </summary>
        /// <param name="OrderNo"></param>
        /// <param name="FileNo"></param>
        /// <returns></returns>
        [PortalAuthorizationAttribute]
        public JsonResult DeleteAttachment(string OrderNo, string FileNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            string customerNo = GetPortLoginUser().CustomerNo;
            Order order = Context.Order.FirstOrDefault(m => m.OrderNo == OrderNo && m.CustomerNo == customerNo && !m.Approved);
            if (order == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                OrderAttachment attachment = Context.OrderAttachment.FirstOrDefault(m => m.OrderNo == OrderNo && m.AttachmentNo == FileNo && m.UploadByCustomer);
                if (attachment == null)
                {
                    result.Data = new { code = 1 };
                }
                else
                {
                    Context.OrderAttachment.DeleteObject(attachment);

                    Context.SaveChanges();
                    result.Data = new { code = 0, FileNo = attachment.AttachmentNo };

                    try
                    {
                        System.IO.File.Delete(attachment.FilePath);
                    }
                    catch
                    {
                        AddErrorMessage(string.Format("删除附件失败：{0}", attachment.FilePath));
                    }
                }
            }
            return result;
        }
        
        [PortalAuthorizationAttribute]
        public ActionResult EditOrder(string OrderNo)
        {
            if (string.IsNullOrEmpty(OrderNo))
            {
                return Redirect("/Portal/Index");
            }

            string customerNo = GetPortLoginUser().CustomerNo;
            OrderModel model = new OrderModel();
            Order order = Context.Order.Where(m => m.OrderNo == OrderNo && m.CustomerNo == customerNo).FirstOrDefault();
            model.BindFromOrderEntity(order);
            model.IsAdd = "0";

            if (order == null)
            {
                return Redirect("/Portal/Index");
            }

            model.DdlContact = Context.Contact.Where(m => m.CustomerNo == customerNo).Select(m => new SimpleItemList { ItemValue = m.ContactNo, ItemText = m.ContactName + (String.IsNullOrEmpty(m.Mobile) ? "" : " " + m.Mobile) + (String.IsNullOrEmpty(m.Phone) ? "" : " " + m.Phone) }).ToList();
            model.DdlContact.Insert(0, new SimpleItemList() { ItemText = "", ItemValue = "" });
            model.hContactNo = model.ContactNo;

            return View(model);
        }       

        [PortalAuthorizationAttribute]      
        public JsonResult CreateNewOrder(string BasicInfo, string DetailInfo)
        {            
            JsonResult result = new JsonResult();
            JavaScriptSerializer js = new JavaScriptSerializer();


            List<OrderDetailModel> details = js.Deserialize(DetailInfo, typeof(List<OrderDetailModel>)) as List<OrderDetailModel>;
           
            List<IdNumber> newNos = new List<IdNumber>();

            foreach (OrderDetailModel d in details)
            {
                Order order = js.Deserialize(BasicInfo, typeof(Order)) as Order;
                string newOrderNo = GetNewIdNumber(IdNumberType.Order);
                newNos.Add(new IdNumber() { Type = IdNumberType.Order, No = newOrderNo });
                order.OrderNo = newOrderNo;
                order.CompanyNo = GetPortLoginUser().CompanyNo;
                order.CustomerNo = GetPortLoginUser().CustomerNo;
                order.Creator = GetPortLoginUser().LoginName;
                order.CreatedTime = DateTime.Now;
                order.IsActive = true;
                order.OrderTemplate = OrderTemplate;
                order.QueryCode = GetOrderQueryNo();
                order.Approved = false;
                order.Amount = 0;
                order.Price = 0;
                order.FactoryPrice = null;
                order.FactoryAmount = null;
                order.TransactionDate = DateTime.Now;

                SetOrderPaymentStatus(order);
                order.OrderStatusNo = CompanyNo + ORDER_STATUS_CREATED;

                order.OrderName = d.Content;
                order.Category = d.Category;
                order.CategoryName = d.CategoryName;
                order.ReportCategory = d.ReportCategory;
                order.Detail = d.Detail;
                order.DetailText = string.IsNullOrEmpty(d.DetailText) ? "" : d.DetailText;
                order.Number = d.Number;
                order.Memo = d.Memo;

                Context.Order.AddObject(order);

                OrderLog log = new OrderLog();
                log.OrderNo = order.OrderNo;
                log.LogDate = DateTime.Now;
                log.IsPublic = true;
                log.Operation = "客户自助创建订单";
                log.UserName = GetPortLoginUser().LoginName;
                Context.OrderLog.AddObject(log);
            }

            try
            {
                Context.SaveChanges();
                result.Data = new { code = 0 };

            }
            catch (Exception ex)
            {              
                    PutbackNos(newNos);                

                throw ex;
            }

            return result;
        }
      
        [PortalAuthorizationAttribute]
        public ActionResult CreateOrder()
        {
            OrderModel model = new OrderModel();
            string customerNo = GetPortLoginUser().CustomerNo;
            model.DdlContact = Context.Contact.Where(m => m.CustomerNo == customerNo).Select(m => new SimpleItemList { ItemValue = m.ContactNo, ItemText = m.ContactName + (String.IsNullOrEmpty(m.Mobile) ? "" : " " + m.Mobile) + (String.IsNullOrEmpty(m.Phone) ? "" : " " + m.Phone) }).ToList();
            model.DdlContact.Insert(0, new SimpleItemList() { ItemText = "", ItemValue = "" });
            model.OrderNo = AUTO_NUMBER;
            model.IsAdd = "1";
            model.OrderTemplate = OrderTemplate;

            return View("EditOrder", model);
        }

        [PortalAuthorizationAttribute]
        public JsonResult GetOrderDetail(string OrderNo)
        {
            JsonResult result = new JsonResult();
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            if (string.IsNullOrEmpty(OrderNo))
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else
            {
                List<JsonOrder> details = Context.Order.Where(m => m.OrderNo == OrderNo).Select(m => new JsonOrder
                {
                    OrderNo = m.OrderNo,
                    Content = m.OrderName,
                    Category = m.Category,
                    CategoryName = m.CategoryName,
                    ReportCategory = m.ReportCategory,
                    DetailString = m.Detail,
                    DetailText = m.DetailText,
                    Number = m.Number,
                    Price = m.Price,
                    Amount = m.Amount,
                    FactoryNo = m.FactoryNo,
                    FactoryAmount = m.FactoryAmount,
                    FactoryPrice = m.FactoryPrice,
                    WorkFlowNo = m.WorkFlowNo,
                    ExpectDeliveryDate = m.ExpectDeliveryDate,
                    Memo = m.Memo
                }).ToList();

                // Why need to deserialize the Detail field(string)?
                // If we not deserialize the Detail field, then here the string will be Jsonable(with \" to represent "), 
                // and later on the client side, the \ itself will be changed to \\, that lead to many \ after multiple edit.
                JavaScriptSerializer json = new JavaScriptSerializer();
                foreach (JsonOrder o in details)
                {
                    o.Detail = json.Deserialize<object>(o.DetailString);
                    o.DetailString = o.DetailString;

                }
                result.Data = new { code = 0, data = details };
            }
            return result;
        }
       
        [PortalAuthorizationAttribute]
        public JsonResult UpdateOrder(string BasicInfo, string DetailInfo)
        {
            JsonResult result = new JsonResult();
            JavaScriptSerializer js = new JavaScriptSerializer();
            Order order = js.Deserialize(BasicInfo, typeof(Order)) as Order;
            List<OrderDetailModel> details = js.Deserialize(DetailInfo, typeof(List<OrderDetailModel>)) as List<OrderDetailModel>;

            string customerNo = GetPortLoginUser().CustomerNo;
            Order orignialOrder = Context.Order.Where(m => m.OrderNo == order.OrderNo && m.CustomerNo == customerNo).FirstOrDefault();

            if (orignialOrder == null)
            {
                result.Data = new { code = 1, message = MSG_NoEntityFound };
            }
            else if (orignialOrder.Approved)
            {
                result.Data = new { code = 1, message = "订单已经被确认，无法更改" };
            }
            else
            {
                OrderDetailModel d = details[0];
                order.Amount = Math.Round(d.Amount, 2);
                if (d.FactoryAmount.HasValue)
                {
                    order.FactoryAmount = Math.Round(d.FactoryAmount.Value, 2);
                }
                else
                {
                    order.FactoryAmount = null;
                }

                orignialOrder.OrderName = d.Content;
                orignialOrder.ContactNo = order.ContactNo;
                orignialOrder.Contact = order.Contact;
                orignialOrder.Memo = d.Memo;



                orignialOrder.Detail = d.Detail;
                orignialOrder.DetailText = d.DetailText;
                orignialOrder.Number = d.Number;
                orignialOrder.Category = d.Category;
                orignialOrder.CategoryName = d.CategoryName;
                orignialOrder.ReportCategory = d.ReportCategory;
            }

            Context.SaveChanges();
            result.Data = new { code = 0 };

            return result;
        }
    }
}
